/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_TASK_INTERNAL_H
#define IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_TASK_INTERNAL_H

#include "RemoteCommunicationKit/rcp.h"
#include "imageknife_task.h"
#include "imageknife_request_internal.h"
#include "log.h"
#include <future>
#include <multimedia/image_framework/image/image_source_native.h>

namespace ImageKnifePro {

class DecodeImageSource {
public:
    DecodeImageSource(uint8_t *buffer, uint32_t length);
    ~DecodeImageSource();
    OH_ImageSourceNative *GetImageSourceNative() const;
    Image_ErrorCode GetErrorCode() const;
private:
    Image_ErrorCode errorCode_;
    OH_ImageSourceNative *imageSource_ = nullptr;
};

class ImageKnifeTaskInternal : public ImageKnifeTask {
public:
    std::string memoryKey;
    std::string fileKey;
    std::mutex cancelMutex_;

    // 标记图片是否有缓存文件
    bool foundFileCache = false;
    // 在写文件缓存完成后的子线程取得处理preloadCache请求的函数
    std::promise<std::function<void(bool)>> promisePreloadCache;

    // 网络下载session，用于取消下载
    Rcp_Session *rcpSession = nullptr;
    // 网络下载request，用于取消下载
    Rcp_Request *rcpRequest = nullptr;
    // 网络下载, http响应数据，由product.imageBuffer的删除器析构
    Rcp_Response *rcpResponse = nullptr;

    ImageKnifeTaskInternal(ImageRequestType type, std::shared_ptr<ImageKnifeRequestInternal> request,
        ImageSource *imageSrc) : type_(type), request_(request), imageSrc_(imageSrc)
    {
        SetIsAnimator();
    }

    ImageKnifeTaskInternal(std::shared_ptr<uint8_t[]> buffer, uint32_t bufferLength, uint32_t frameIndex,
                           ImageRequestType type, std::shared_ptr<ImageKnifeRequestInternal> request);

    ~ImageKnifeTaskInternal() override
    {
    }

    Interceptor *GetCurrentInterceptor() const
    {
        return interceptor_;
    }

    void SetInterceptor(Interceptor *interceptor)
    {
        interceptor_ = interceptor;
    }

    void ClearInterceptorPtr()
    {
        interceptor_ = nullptr;
    }

    bool IsSuccess() const
    {
        return success_;
    }

    void MarkSuccess()
    {
        success_ = true;
    }

    void FatalError(std::string errorInfo)
    {
        fatalError_ = true;
        EchoError("[Fatal Error] " + errorInfo);
    }

    void EchoError(std::string errorInfo) override
    {
        std::string source;
        if (interceptor_ != nullptr) {
            source = " (" + interceptor_.load()->name + ") ";
        }
        lastError_ = GetTaskInfo(type_, request_) + errorInfo + source;
        IMAGE_KNIFE_LOG(LOG_ERROR, "%{public}s", lastError_.c_str());
    }

    std::string GetLastError() const
    {
        return lastError_;
    }

    bool IsFatalErrorHappened()
    {
        return fatalError_;
    }

    static std::string GetTaskInfo(ImageRequestType type, std::shared_ptr<ImageKnifeRequestInternal> request);
    std::string GetTaskInfo() const;

    std::string GetDisplayPixelmapInfo() const;

    Image_Size GetDesiredImageSize() const override;

    OH_ImageSourceNative *GetImageSourceNative() const;
    uint32_t GetImageSourceFrameCount() const;

    bool IsAnimator() const override
    {
        return isAnimator_;
    }

    bool IsAnimationImage() const
    {
        return isAnimationImage_;
    }

    ImageSource *GetImageSource() const override;

    ImageRequestType GetImageRequestType() const override;

    std::shared_ptr<ImageKnifeRequest> GetImageKnifeRequest() const override;

    std::shared_ptr<ImageKnifeRequestInternal> GetImageKnifeRequestInternal() const;

    ImageFormat GetImageBufferFormat() const override;
    void QueryImageBufferFormat();

    void SetFallbackUrl(std::string fallbackUrl);

    void MarkFileCacheNeedRename();
    bool IsFileCacheNeedRename() const;
    bool IsFrameDecodeMode() const;
    int GetDecodeFrameIndex() const override;
    void SetImageFormat(ImageFormat format);
    void SetDecodeImageSource(std::shared_ptr<DecodeImageSource> decodeImageSource);
    std::shared_ptr<DecodeImageSource> GetDecodeImageSource() const;
    void SetDesiredSize(Image_Size desiredSize);

    void MarkDecodeFrameFinished();
    bool IsDecodeFrameFinished() const;
private:
    std::shared_ptr<ImageKnifeRequestInternal> request_ = nullptr;
    ImageRequestType type_ = ImageRequestType::MAIN_SRC;
    ImageSource *imageSrc_ = nullptr;
    ImageSource fallbackUrl_;

    // 用于Default DecodeInterceptor 待解码图片源
    std::shared_ptr<DecodeImageSource> decodeImageSource_ = nullptr;
    uint32_t frameCount_ = 0;
    uint32_t frameIndex_ = 0;
    Image_Size desiredImageSize_ = {.width = 0, .height = 0};

    std::atomic<Interceptor*> interceptor_ = nullptr;
    bool success_ = false;
    bool fatalError_ = false;
    std::string lastError_;

    bool fileCacheNeedRename_ = false;
    // 组件是否为Animator
    bool isAnimator_ = false;
    // 图片source是否为动图类型
    bool isAnimationImage_ = false;
    bool isFrameDecodeMode_ = false;
    bool isDecodeFrameFinished_ = false;
    ImageFormat imageBufferFormat_ = ImageFormat::UNKNOWN;
    void SetIsAnimator();
    void CheckDecodeMode(const uint32_t &width, const uint32_t &height);
};
} // end of namespace
#endif // IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_TASK_INTERNAL_H
